package com.example.coroutinelearn

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.runBlocking
import org.junit.Test

/**
 * @author huangzehui
 * @date 1/6/2024 上午1:18 周六
 * @description
 *
 * 通过 Flow 异步返回多个值
 * https://www.bilibili.com/video/BV1uo4y1y7ZF?p=57&vd_source=e07cc8cc94eb22bd76722071b03cd199
 */
class FlowTest {

    fun simpleFlow() = flow<Int> {
        for (i in 1..3) {
            delay(1000)
            emit(i)
        }
    }

    fun simpleFlow2() = flow<Int> {
        // flow 是冷流
        // 这里的代码都是 调用了 collect 次会执行, 再 testFlow2 体现
        println("Flow Started")
        for (i in 0 until 3) {
            delay(1000)
            emit(i)
        }
    }

    @Test
    fun testFlow1() {
        runBlocking {
            simpleFlow().collect {
                println("testFlow1 = $it")
            }
        }
        println("testFlow1 end")
    }

    @Test
    fun testFlow2() {
        runBlocking {
            val flow = simpleFlow2()
            println("start collect")
            flow.collect {
                println("collect1 = ${it}")
            }
            println("again start collect")
            flow.collect {
                println("collect2 = ${it}")
            }
        }
    }

    @Test
    fun `test flow continuation`() {
        // 测试流的操作符号
        runBlocking {
            (1..5).asFlow()
                .filter {
                    it % 2 == 0
                }
                .map {
                    "string ${it}"
                }
                .collect {
                    println("hello ${it}")
                }
        }
    }

    @Test
    fun `test flow builder`() = runBlocking {
        // 测试流的构建器
        // 构建器1：flow<Int>{}
        // 构建器2：flowOf()
        // 构建器3：asFlow() 函数
        flowOf("One", "Two", "Three").onEach {
            // 间隔 1秒 发送一个
            delay(1000)
        }
            .collect {
                println("Hello ${it}")
            }
    }

    fun simpleFlow3() = flow<Int> {
        println("simpleFlow3 ${Thread.currentThread().name}")
        for (i in 0 until 3) {
            delay(1000)
            emit(i)
        }
    }

    @Test
    fun testFlow3() = runBlocking {
        simpleFlow3()
            .flowOn(Dispatchers.Default)
            .collect {
                println("collect ${it} = ${Thread.currentThread().name}")
            }
    }


    fun events() = (1..3).asFlow()
        .onEach { delay(1000) }
        .flowOn(Dispatchers.Default)


    suspend fun CoroutineScope.getHh() = async {
        
    }

    @Test
    fun testFlow4() = runBlocking {
        events().onEach {
            println("Hello kkk ${it} ${Thread.currentThread().name}")
        }
//            .launchIn(CoroutineScope(Dispatchers.IO))
            .launchIn(this)
            .join()
    }

}